package com.study.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.study.springcloud.consts.Constant;
import com.study.springcloud.response.ResultObject;
import com.study.springcloud.serivce.GoodsRemoteClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.TimeUnit;

/**
 * @Author Chen Jie
 * @Date 2022/3/5 14:53
 * @Version 1.0
 */
@Slf4j
@RestController
public class PortalController {
    private static final String GOODS_SERVICE_URL = "http://127.0.0.1:7001/service/goods";

    //此处使用的是spring.application.name, 不是eureka.instance.instance-id!
    private static final String GOODS_SERVICE_URL_2 = "http://springcloud-service-goods/service/goods";

    /**
     * 类似的还有apache.HttpClient、java.net.URL相关类
     */
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private GoodsRemoteClient goodsRemoteClient;

    @Autowired
    private HttpHeaders httpHeaders;

    @GetMapping("/cloud/goods")
    public ResultObject goods() {
        //使用RestTemplate进行HTTP的远程调用
//        ResponseEntity<ResultObject> responseEntity = restTemplate.getForEntity(GOODS_SERVICE_URL_2, ResultObject.class);

        //带安全认证的调用
        ResponseEntity<ResultObject> responseEntity = restTemplate.exchange(GOODS_SERVICE_URL_2, HttpMethod.GET, new HttpEntity<>(httpHeaders), ResultObject.class);

        log.info("请求头: {}", responseEntity.getHeaders());
        log.info("响应状态码: {}", responseEntity.getStatusCode());
        log.info("响应状态码的值: {}", responseEntity.getStatusCodeValue());
        return responseEntity.getBody();
    }

    @GetMapping("/cloud/goodsFeign")
    public ResultObject goodsFeign() {
        return goodsRemoteClient.goods();
    }

    @HystrixCommand(fallbackMethod = "fallbackWithThrowable")
    @GetMapping("/cloud/goodsHystrix")
    public ResultObject goodsHystrix() {
        return restTemplate.getForEntity(GOODS_SERVICE_URL_2, ResultObject.class).getBody();
    }

    public ResultObject fallback() {
        return new ResultObject(Constant.ERROR, "Hystrix进行了熔断处理....", null);
    }

    public ResultObject fallbackWithThrowable(Throwable throwable) {
        throwable.printStackTrace();
        return new ResultObject(Constant.ERROR, "Hystrix进行了熔断处理....", null);
    }

    @GetMapping("/cloud/goodsFeignHystrix")
    public ResultObject goodsFeignHystrix() {
        return goodsRemoteClient.goods();
    }

    @HystrixCommand(fallbackMethod = "fallback",
            commandProperties = {
                    //命令执行知否开启超时, 默认为true
                    @HystrixProperty(name = "execution.timeout.enabled", value = "true"),
                    //指定命令执行的超时时间, 默认为1秒
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
            }
    )
    @GetMapping("/cloud/goodsHystrixTimeout")
    public ResultObject goodsHystrixTimeout() throws InterruptedException {
        ResultObject result = restTemplate.getForEntity(GOODS_SERVICE_URL_2, ResultObject.class).getBody();
        TimeUnit.SECONDS.sleep(8);
        return result;
    }

    //    @HystrixCommand(fallbackMethod = "fallback",
//            commandProperties = {
//                    //命令执行知否开启超时, 默认为true
//                    @HystrixProperty(name = "execution.timeout.enabled", value = "true"),
//                    //指定命令执行的超时时间, 默认为1秒
//                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
//            }
//    )
    @GetMapping("/cloud/goodsFeignHystrixTimeout")
    public ResultObject goodsFeignHystrixTimeout() throws InterruptedException {
        return goodsRemoteClient.goods();
    }

    @HystrixCommand(fallbackMethod = "fallback", ignoreExceptions = {RuntimeException.class})
    @GetMapping("/cloud/goodsHystrixIgnoreExceptions")
    public ResultObject goodsHystrixIgnoreExceptions() throws InterruptedException {
        ResultObject result = restTemplate.getForEntity(GOODS_SERVICE_URL_2, ResultObject.class).getBody();

        if (1 == 1) {
            throw new RuntimeException("has error...");
        }

        return result;
    }

//    @HystrixCommand(ignoreExceptions = {RuntimeException.class})
//    @GetMapping("/cloud/goodsFeignHystrixIgnoreExceptions")
//    public ResultObject goodsFeignHystrixIgnoreExceptions() throws InterruptedException {
//        return goodsRemoteClient.goods();
//    }
}
